/*            Copyright(c) 2006-2008 Dave Sexton           *
 * http://www.codeplex.com/DocProject                      *
 * http://www.codeplex.com/DocProject/Project/License.aspx *
 ***********************************************************/
using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Collections.Specialized;
using EnvDTE;
using System.Configuration;
using System.Globalization;
using System.Xml;
using DaveSexton.DocProject.Resources;
using System.Xml.XPath;

namespace DaveSexton.DocProject
{
	[Serializable]
	[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2240:ImplementISerializableCorrectly")]
	public class BufferedSettingsDictionary<TKey, TValue> : BufferedSettingsDictionaryBase<TKey, TValue>
	{
		#region Public Properties
		public override bool CanCommit
		{
			get
			{
				return true;
			}
		}

		public IDictionary<TKey, TValue> CommitDictionary
		{
			get
			{
				return commitDictionary;
			}
		}
		#endregion

		#region Private / Protected
		private readonly IDictionary<TKey, TValue> commitDictionary;
		#endregion

		#region Constructors
		/// <summary>
		/// Constructs a new instance of the <see cref="BufferedSettingsDictionary" /> class.
		/// </summary>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1304:SpecifyCultureInfo", MessageId = "DaveSexton.DocProject.BufferedSettingsDictionaryBase`2<type parameter.TKey,type parameter.TValue>.#ctor")]
		public BufferedSettingsDictionary()
		{
			commitDictionary = new Dictionary<TKey, TValue>();
		}

		/// <summary>
		/// Constructs a new instance of the <see cref="BufferedSettingsDictionary" /> class.
		/// </summary>
		public BufferedSettingsDictionary(CultureInfo culture)
			: base(culture)
		{
			commitDictionary = new Dictionary<TKey, TValue>();
		}

		/// <summary>
		/// Constructs a new instance of the <see cref="BufferedSettingsDictionary" /> class.
		/// </summary>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1304:SpecifyCultureInfo", MessageId = "DaveSexton.DocProject.BufferedSettingsDictionaryBase`2<type parameter.TKey,type parameter.TValue>.#ctor")]
		public BufferedSettingsDictionary(int capacity)
			: base(capacity)
		{
			commitDictionary = new Dictionary<TKey, TValue>(capacity);
		}

		/// <summary>
		/// Constructs a new instance of the <see cref="BufferedSettingsDictionary" /> class.
		/// </summary>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1304:SpecifyCultureInfo", MessageId = "DaveSexton.DocProject.BufferedSettingsDictionaryBase`2<type parameter.TKey,type parameter.TValue>.#ctor")]
		public BufferedSettingsDictionary(IEqualityComparer<TKey> comparer)
			: base(comparer)
		{
			commitDictionary = new Dictionary<TKey, TValue>(comparer);
		}

		/// <summary>
		/// Constructs a new instance of the <see cref="BufferedSettingsDictionary" /> class.
		/// </summary>
		public BufferedSettingsDictionary(CultureInfo culture, int capacity)
			: base(culture, capacity)
		{
			commitDictionary = new Dictionary<TKey, TValue>(capacity);
		}

		/// <summary>
		/// Constructs a new instance of the <see cref="BufferedSettingsDictionary" /> class.
		/// </summary>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1304:SpecifyCultureInfo", MessageId = "DaveSexton.DocProject.BufferedSettingsDictionaryBase`2<type parameter.TKey,type parameter.TValue>.#ctor")]
		public BufferedSettingsDictionary(int capacity, IEqualityComparer<TKey> comparer)
			: base(capacity, comparer)
		{
			commitDictionary = new Dictionary<TKey, TValue>(comparer);
		}

		/// <summary>
		/// Constructs a new instance of the <see cref="BufferedSettingsDictionary" /> class.
		/// </summary>
		public BufferedSettingsDictionary(CultureInfo culture, IEqualityComparer<TKey> comparer)
			: base(culture, comparer)
		{
			commitDictionary = new Dictionary<TKey, TValue>(comparer);
		}

		/// <summary>
		/// Constructs a new instance of the <see cref="BufferedSettingsDictionary" /> class.
		/// </summary>
		public BufferedSettingsDictionary(CultureInfo culture, int capacity, IEqualityComparer<TKey> comparer)
			: base(culture, capacity, comparer)
		{
			commitDictionary = new Dictionary<TKey, TValue>(capacity, comparer);
		}

		/// <summary>
		/// Constructs a new instance of the <see cref="BufferedSettingsDictionary" /> class.
		/// </summary>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1304:SpecifyCultureInfo", MessageId = "DaveSexton.DocProject.BufferedSettingsDictionaryBase`2<type parameter.TKey,type parameter.TValue>.#ctor")] 
		public BufferedSettingsDictionary(IDictionary<TKey, TValue> commitDictionary)
		{
			if (commitDictionary == null)
				throw new ArgumentNullException("commitDictionary");

			this.commitDictionary = commitDictionary;
		}

		/// <summary>
		/// Constructs a new instance of the <see cref="BufferedSettingsDictionary" /> class.
		/// </summary>
		public BufferedSettingsDictionary(IDictionary<TKey, TValue> commitDictionary, CultureInfo culture)
			: base(culture)
		{
			if (commitDictionary == null)
				throw new ArgumentNullException("commitDictionary");

			this.commitDictionary = commitDictionary;
		}

		/// <summary>
		/// Constructs a new instance of the <see cref="BufferedSettingsDictionary" /> class.
		/// </summary>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1304:SpecifyCultureInfo", MessageId = "DaveSexton.DocProject.BufferedSettingsDictionaryBase`2<type parameter.TKey,type parameter.TValue>.#ctor")]
		public BufferedSettingsDictionary(IDictionary<TKey, TValue> commitDictionary, int capacity)
			: base(capacity)
		{
			if (commitDictionary == null)
				throw new ArgumentNullException("commitDictionary");

			this.commitDictionary = commitDictionary;
		}

		/// <summary>
		/// Constructs a new instance of the <see cref="BufferedSettingsDictionary" /> class.
		/// </summary>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1304:SpecifyCultureInfo", MessageId = "DaveSexton.DocProject.BufferedSettingsDictionaryBase`2<type parameter.TKey,type parameter.TValue>.#ctor")]
		public BufferedSettingsDictionary(IDictionary<TKey, TValue> commitDictionary, IEqualityComparer<TKey> comparer)
			: base(comparer)
		{
			if (commitDictionary == null)
				throw new ArgumentNullException("commitDictionary");

			this.commitDictionary = commitDictionary;
		}

		/// <summary>
		/// Constructs a new instance of the <see cref="BufferedSettingsDictionary" /> class.
		/// </summary>
		public BufferedSettingsDictionary(IDictionary<TKey, TValue> commitDictionary, CultureInfo culture, int capacity)
			: base(culture, capacity)
		{
			if (commitDictionary == null)
				throw new ArgumentNullException("commitDictionary");

			this.commitDictionary = commitDictionary;
		}

		/// <summary>
		/// Constructs a new instance of the <see cref="BufferedSettingsDictionary" /> class.
		/// </summary>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1304:SpecifyCultureInfo", MessageId = "DaveSexton.DocProject.BufferedSettingsDictionaryBase`2<type parameter.TKey,type parameter.TValue>.#ctor")]
		public BufferedSettingsDictionary(IDictionary<TKey, TValue> commitDictionary, int capacity, IEqualityComparer<TKey> comparer)
			: base(capacity, comparer)
		{
			if (commitDictionary == null)
				throw new ArgumentNullException("commitDictionary");

			this.commitDictionary = commitDictionary;
		}

		/// <summary>
		/// Constructs a new instance of the <see cref="BufferedSettingsDictionary" /> class.
		/// </summary>
		public BufferedSettingsDictionary(IDictionary<TKey, TValue> commitDictionary, CultureInfo culture, IEqualityComparer<TKey> comparer)
			: base(culture, comparer)
		{
			if (commitDictionary == null)
				throw new ArgumentNullException("commitDictionary");

			this.commitDictionary = commitDictionary;
		}

		/// <summary>
		/// Constructs a new instance of the <see cref="BufferedSettingsDictionary" /> class.
		/// </summary>
		public BufferedSettingsDictionary(IDictionary<TKey, TValue> commitDictionary, CultureInfo culture, int capacity, IEqualityComparer<TKey> comparer)
			: base(culture, capacity, comparer)
		{
			if (commitDictionary == null)
				throw new ArgumentNullException("commitDictionary");

			this.commitDictionary = commitDictionary;
		}

		/// <summary>
		/// Constructs a new instance of the <see cref="BufferedSettingsDictionary" /> class for deserialization.
		/// </summary>
		protected BufferedSettingsDictionary(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
			: base(info, context)
		{
		}
		#endregion

		#region Methods
		public override TValue GetCommittedValue(TKey name)
		{
			if (name == null)
				throw new ArgumentNullException("name");

			return commitDictionary[name];
		}

		public override void SetCommittedValue(TKey name, TValue value)
		{
			if (name == null)
				throw new ArgumentNullException("name");

			commitDictionary[name] = value;
		}

		public override bool IsDirty(TKey name)
		{
			if (name == null)
				throw new ArgumentNullException("name");

			if (!ContainsKey(name))
				return false;
			else if (typeof(TValue).IsValueType)
				return !this[name].Equals(commitDictionary[name]);
			else
				return object.Equals(this[name], commitDictionary[name]);
		}

		public virtual bool IsDirty(TKey name, IEqualityComparer<TValue> comparer)
		{
			if (name == null)
				throw new ArgumentNullException("name");

			if (!ContainsKey(name))
				return false;
			else
				return !comparer.Equals(this[name], commitDictionary[name]);
		}

		public override bool IsCommitted(TKey name)
		{
			if (name == null)
				throw new ArgumentNullException("name");

			return commitDictionary.ContainsKey(name);
		}

		public override void Delete(TKey name)
		{
			if (name == null)
				throw new ArgumentNullException("name");

			commitDictionary.Remove(name);
		}
		#endregion
	}
}
